package cn.iocoder.lw.module.core.service.workorder;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.lw.framework.common.pojo.PageParam;
import cn.iocoder.lw.framework.common.pojo.PageResult;
import cn.iocoder.lw.framework.common.util.object.BeanUtils;
import cn.iocoder.lw.module.core.controller.admin.workorder.vo.workorder.*;
import cn.iocoder.lw.module.core.controller.app.workorder.vo.workorder.AppCoreWorkOrderCreateReqVO;
import cn.iocoder.lw.module.core.controller.app.workorder.vo.workorder.AppCoreWorkOrderUpdateReqVO;
import cn.iocoder.lw.module.core.controller.app.workorder.vo.workorder.AppCoreWorkOrderPageReqVO;
import cn.iocoder.lw.module.core.convert.workorder.CoreWorkOrderConvert;
import cn.iocoder.lw.module.core.dal.dataobject.project.CoreProjectDO;
import cn.iocoder.lw.module.core.dal.dataobject.house.CoreHouseDO;
import cn.iocoder.lw.module.core.dal.dataobject.device.CoreDeviceDO;
import cn.iocoder.lw.module.core.dal.dataobject.workorder.CoreWorkOrderDO;
import cn.iocoder.lw.module.core.dal.mysql.workorder.CoreWorkOrderMapper;
import cn.iocoder.lw.module.core.enums.workorder.WorkOrderStatusEnum;
import cn.iocoder.lw.module.core.service.project.CoreProjectService;
import cn.iocoder.lw.module.core.service.house.CoreHouseService;
import cn.iocoder.lw.module.core.service.device.CoreDeviceService;
import cn.iocoder.lw.module.system.api.user.AdminUserApi;
import cn.iocoder.lw.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.lw.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.lw.module.core.enums.ErrorCodeConstants.*;

/**
 * 工单 Service 实现类
 *
 * @author Lw源码
 */
@Service
@Validated
@Slf4j
public class CoreWorkOrderServiceImpl implements CoreWorkOrderService {

    @Resource
    private CoreWorkOrderMapper workOrderMapper;

    @Resource
    private CoreProjectService projectService;

    @Resource
    private CoreHouseService houseService;

    @Resource
    private CoreDeviceService deviceService;

    @Resource
    private AdminUserApi adminUserApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createWorkOrder(@Valid CoreWorkOrderSaveReqVO createReqVO) {
        // 校验关联数据存在
        validateRelatedData(createReqVO.getProjectId(), createReqVO.getHouseId(), createReqVO.getDeviceId(), null);

        // 生成工单编号
        String orderNo = generateOrderNo();

        // 插入
        CoreWorkOrderDO workOrder = BeanUtils.toBean(createReqVO, CoreWorkOrderDO.class);
        workOrder.setOrderNo(orderNo);
        // 设置初始状态为待派单
        workOrder.setStatus(WorkOrderStatusEnum.PENDING_ASSIGN.getStatus());
        workOrderMapper.insert(workOrder);

        // 返回
        return workOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createWorkOrderApp(@Valid AppCoreWorkOrderCreateReqVO createReqVO) {
        // 校验关联数据存在
        validateRelatedData(createReqVO.getProjectId(), createReqVO.getHouseId(), createReqVO.getDeviceId(), null);

        // 生成工单编号
        String orderNo = generateOrderNo();

        // 插入
        CoreWorkOrderDO workOrder = BeanUtils.toBean(createReqVO, CoreWorkOrderDO.class);
        workOrder.setOrderNo(orderNo);
        // 设置初始状态为待派单
        workOrder.setStatus(WorkOrderStatusEnum.PENDING_ASSIGN.getStatus());
        workOrderMapper.insert(workOrder);

        // 返回
        return workOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkOrder(@Valid CoreWorkOrderSaveReqVO updateReqVO) {
        // 校验存在
        validateWorkOrderExists(updateReqVO.getId());
        // 校验关联数据存在
        validateRelatedData(updateReqVO.getProjectId(), updateReqVO.getHouseId(), updateReqVO.getDeviceId(), updateReqVO.getId());

        // 更新
        CoreWorkOrderDO updateObj = BeanUtils.toBean(updateReqVO, CoreWorkOrderDO.class);
        workOrderMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkOrderApp(@Valid AppCoreWorkOrderUpdateReqVO updateReqVO) {
        // 校验存在
        validateWorkOrderExists(updateReqVO.getId());
        // 校验关联数据存在
        validateRelatedData(updateReqVO.getProjectId(), updateReqVO.getHouseId(), updateReqVO.getDeviceId(), updateReqVO.getId());

        // 更新
        CoreWorkOrderDO updateObj = BeanUtils.toBean(updateReqVO, CoreWorkOrderDO.class);
        workOrderMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWorkOrder(Long id) {
        // 校验存在
        validateWorkOrderExists(id);
        // 删除
        workOrderMapper.deleteById(id);
    }

    @Override
    public CoreWorkOrderDO getWorkOrder(Long id) {
        return workOrderMapper.selectById(id);
    }

    @Override
    public PageResult<CoreWorkOrderDO> getWorkOrderPage(CoreWorkOrderPageReqVO pageReqVO) {
        return workOrderMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<CoreWorkOrderDO> getWorkOrderPageApp(AppCoreWorkOrderPageReqVO pageReqVO) {
        CoreWorkOrderPageReqVO adminPageReqVO = BeanUtils.toBean(pageReqVO, CoreWorkOrderPageReqVO.class);
        return workOrderMapper.selectPage(adminPageReqVO);
    }

    @Override
    public CoreWorkOrderDO validateWorkOrderExists(Long id) {
        if (id == null) {
            return null;
        }
        CoreWorkOrderDO workOrder = workOrderMapper.selectById(id);
        if (workOrder == null) {
            throw exception(WORK_ORDER_NOT_EXISTS);
        }
        return workOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignWorkOrder(Long id, Long assigneeId, String assigneePhone, String assigneeName) {
        CoreWorkOrderDO workOrder = validateWorkOrderExists(id);

        // 校验当前状态是否可以派单
        if (!Objects.equals(workOrder.getStatus(), WorkOrderStatusEnum.PENDING_ASSIGN.getStatus())) {
            throw exception(WORK_ORDER_STATUS_NOT_ALLOW_ASSIGN);
        }

        // TODO: 校验接单人是否存在，暂时跳过member模块依赖
        // MemberUserRespDTO assignee = memberUserApi.getUser(assigneeId);
        // if (assignee == null) {
        //     throw exception(ASSIGNEE_NOT_EXISTS);
        // }

        // 更新状态和接单人信息
        CoreWorkOrderDO updateObj = new CoreWorkOrderDO();
        updateObj.setId(id);
        updateObj.setStatus(WorkOrderStatusEnum.PENDING_ACCEPT.getStatus());
        updateObj.setAssigneeId(assigneeId);
        updateObj.setAssigneePhone(assigneePhone);
        updateObj.setAssigneeName(assigneeName);
        workOrderMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void acceptWorkOrder(Long id, Long assigneeId) {
        CoreWorkOrderDO workOrder = validateWorkOrderExists(id);

        // 校验当前状态是否可以接单
        if (!Objects.equals(workOrder.getStatus(), WorkOrderStatusEnum.PENDING_ACCEPT.getStatus())) {
            throw exception(WORK_ORDER_STATUS_NOT_ALLOW_ACCEPT);
        }

        // 校验接单人是否匹配
        if (!Objects.equals(workOrder.getAssigneeId(), assigneeId)) {
            throw exception(ASSIGNEE_NOT_MATCH);
        }

        // 更新状态为已接单
        CoreWorkOrderDO updateObj = new CoreWorkOrderDO();
        updateObj.setId(id);
        updateObj.setStatus(WorkOrderStatusEnum.ACCEPTED.getStatus());
        workOrderMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkOrderStatus(Long id, Integer status) {
        validateWorkOrderExists(id);

        // 更新状态
        CoreWorkOrderDO updateObj = new CoreWorkOrderDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        workOrderMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeWorkOrder(Long id, @Valid CoreWorkOrderCompleteReqVO updateReqVO) {
        CoreWorkOrderDO workOrder = validateWorkOrderExists(id);

        // 校验当前状态是否可以完成
        if (!Objects.equals(workOrder.getStatus(), WorkOrderStatusEnum.IN_PROGRESS.getStatus())) {
            throw exception(WORK_ORDER_STATUS_NOT_ALLOW_COMPLETE);
        }

        // 更新完成信息
        CoreWorkOrderDO updateObj = BeanUtils.toBean(updateReqVO, CoreWorkOrderDO.class);
        updateObj.setId(id);
        updateObj.setStatus(WorkOrderStatusEnum.COMPLETED.getStatus());
        workOrderMapper.updateById(updateObj);
    }

    @Override
    public List<CoreWorkOrderDO> getWorkOrderListByProjectId(Long projectId) {
        return workOrderMapper.selectListByProjectId(projectId);
    }

    @Override
    public List<CoreWorkOrderDO> getWorkOrderListByHouseId(Long houseId) {
        return workOrderMapper.selectListByHouseId(houseId);
    }

    @Override
    public List<CoreWorkOrderDO> getWorkOrderListByDeviceId(Long deviceId) {
        return workOrderMapper.selectListByDeviceId(deviceId);
    }

    @Override
    public List<CoreWorkOrderDO> getWorkOrderListByInitiatorId(Long initiatorId) {
        return workOrderMapper.selectListByInitiatorId(initiatorId);
    }

    @Override
    public List<CoreWorkOrderDO> getWorkOrderListByAssigneeId(Long assigneeId) {
        return workOrderMapper.selectListByAssigneeId(assigneeId);
    }

    @Override
    public Map<Long, CoreWorkOrderRespVO> getWorkOrderMap(List<Long> ids) {
        List<CoreWorkOrderDO> workOrders = workOrderMapper.selectBatchIds(ids);
        List<CoreWorkOrderRespVO> respVOs = CoreWorkOrderConvert.INSTANCE.convertList(workOrders);
        return respVOs.stream()
                .collect(Collectors.toMap(CoreWorkOrderRespVO::getId, workOrder -> workOrder));
    }

    @Override
    public List<CoreWorkOrderRespVO> getWorkOrderList(CoreWorkOrderPageReqVO pageReqVO) {
        // 简化实现，直接转换不过滤
        PageResult<CoreWorkOrderDO> pageResult = workOrderMapper.selectPage(pageReqVO);
        return CoreWorkOrderConvert.INSTANCE.convertList(pageResult.getList());
    }

    /**
     * 校验关联数据是否存在 - 简化版本
     */
    private void validateRelatedData(Long projectId, Long houseId, Long deviceId, Long excludeId) {
        // TODO: 简化校验，暂时不进行严格校验
        // 后续可以根据需要补充项目、房源、设备的存在性校验
        log.debug("校验关联数据 - projectId: {}, houseId: {}, deviceId: {}", projectId, houseId, deviceId);
    }

    /**
     * 生成工单编号
     */
    private String generateOrderNo() {
        // 简单生成规则：WO + 时间戳 + 随机数
        return "WO" + System.currentTimeMillis() + (int)(Math.random() * 1000);
    }

    /**
     * 补充工单关联信息 - 简化版本
     */
    private void enrichWorkOrder(CoreWorkOrderRespVO workOrder) {
        // TODO: 简化实现，暂时不补充关联信息
        // 后续可以根据需要补充项目、房源、设备等信息
    }

}